package com.ff.kvm.mall.service.impl;

import com.ff.kvm.common.dv.payment.PayOrderDV;
import com.ff.kvm.common.dv.payment.*;
import com.ff.kvm.common.eunm.*;
import com.ff.kvm.common.third_util.WXPayUtil;
import com.ff.kvm.common.third_util.ZFBPayUtil;
import com.ff.kvm.common.util.ConvertUtil;
import com.ff.kvm.common.util.MyUtil;
import com.ff.kvm.common.util.UuidUtil;
import com.ff.kvm.common.vo.Response;
import com.ff.kvm.dao.mapper.OrderPaymentMapper;
import com.ff.kvm.dao.model.Order;
import com.ff.kvm.dao.model.OrderPayment;
import com.ff.kvm.mall.helper.DirectIncomeHelper;
import com.ff.kvm.mall.service.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;

@Service
public class PaymentServiceImpl implements PaymentService {


    private final Logger log = LoggerFactory.getLogger(getClass());

    @Value("spring.profiles.active")
    private String envir;

    private String ORDER_DESCRIPTION = "康丽美购物";
    private String RECHARGE_ORDER_DESCRIPTION = "康丽美充值";


    @Autowired
    private OrderPaymentMapper orderPaymentMapper;

    @Autowired
    private OrderService orderService;

    @Autowired
    private OrderPriceService orderPriceService;

    @Autowired
    private AccountService accountService;

    @Autowired
    private DirectIncomeHelper directIncomeHelper;


    @Autowired
    private UserService userService;

    @Autowired
    OrderExpressService orderExpressService;

    @Transactional
    @Override
    public synchronized Response<PaymentResult> confirmPayOrder(PayOrderDV payOrderDV) {

        Response<PaymentResult> response = new Response<>();

        if(payOrderDV.getType() == PaymentTypeEnum.SHOPPING.type()){
            Order order = orderService.findOrderById(payOrderDV.getOrderId());

            if(payOrderDV.getPayChannel() == PayChannelEnum.WX.type() || payOrderDV.getPayChannel() == PayChannelEnum.ZFB.type()){
                OrderPayment orderPayment = orderPaymentMapper.findOrderPaymentByOrderNO(order.getNo());
                if(orderPayment != null){
                    response.setData(ConvertUtil.convert(orderPayment.getSign(),PaymentResult.class));
                    response.setCode(StatusEnum.SUCCESS.code());
                    response.setMsg(StatusEnum.SUCCESS.description());
                    return response;
                }
            }

            payOrderDV.setOrderNo(order.getNo());
            payOrderDV.setTotal(MyUtil.float2(orderPriceService.findOrderPriceTotalByOrderId(payOrderDV.getOrderId())));
            payOrderDV.setTitle(ORDER_DESCRIPTION);
        }else if(payOrderDV.getType() == PaymentTypeEnum.RECHARGE.type()){
            payOrderDV.setTotal(payOrderDV.getTotal());
            payOrderDV.setOrderNo(getRechargeNO());
            payOrderDV.setTitle(RECHARGE_ORDER_DESCRIPTION);
        }

        //向商户发起预付订单
        response = createPrePayOrder(payOrderDV);
        if(response.getCode().equals(StatusEnum.SUCCESS.code())){
            //本地保存交易订单
            createOrderPayment(payOrderDV,response.getData());
        }

        return response;
    }

    private void createOrderPayment(PayOrderDV payOrderDV,PaymentResult paymentResult) {

        Date nowTime = new Date();
        OrderPayment orderPayment = new OrderPayment();
        orderPayment.setUserId(payOrderDV.getUserId());
        orderPayment.setOrderId(payOrderDV.getOrderId());
        orderPayment.setOrderNo(payOrderDV.getOrderNo());
        orderPayment.setPayChannel(payOrderDV.getPayChannel());
        orderPayment.setIp(payOrderDV.getIp());
        orderPayment.setStatus(OrderPaymentStatusEnum.PAYMENT.type());
        orderPayment.setTitle(payOrderDV.getTitle());
        orderPayment.setType(payOrderDV.getType());
        orderPayment.setCreateTime(nowTime);

        orderPayment.setTotal(payOrderDV.getTotal());
        if(payOrderDV.getPayChannel() == PayChannelEnum.WX.type()){
            orderPayment.setTradeNo(paymentResult.getPrepayid());
            orderPayment.setSign(MyUtil.toJSON(paymentResult));
        }else if(payOrderDV.getPayChannel() == PayChannelEnum.ZFB.type()){
            orderPayment.setTradeNo(paymentResult.getTrade_no());
            orderPayment.setSign(MyUtil.toJSON(paymentResult));
        }else if(payOrderDV.getPayChannel() == PayChannelEnum.WGJ.type()){
            orderPayment.setTradeNo(paymentResult.getTrade_no());
            orderPayment.setPayTime(nowTime);
            orderPayment.setCompleteTime(nowTime);
            orderPayment.setStatus(OrderPaymentStatusEnum.SUCCESS.type());
        }else if(payOrderDV.getPayChannel() == PayChannelEnum.MD.type()){
            orderPayment.setTradeNo(paymentResult.getTrade_no());
            orderPayment.setPayTime(nowTime);
            orderPayment.setCompleteTime(nowTime);
            orderPayment.setStatus(OrderPaymentStatusEnum.SUCCESS.type());
        }
        orderPaymentMapper.insert(orderPayment);
    }

    private Response<PaymentResult> createPrePayOrder(PayOrderDV payOrderDV) {

        if(!envir.equals("prd") && payOrderDV.getPayChannel() != PayChannelEnum.WGJ.type() && payOrderDV.getPayChannel() != PayChannelEnum.MD.type()){
            payOrderDV.setTotal(0.01D);
        }

        switch (payOrderDV.getPayChannel()){
            case 0://余额支付/充值
                return gwjPay(payOrderDV);
            case 1://微信支付/充值
                return wxPay(payOrderDV);
            case 2://支付宝支付/充值
                return zfbPay(payOrderDV);
            case 3://美豆充值
                return mdRecharge(payOrderDV);
            default:
                Response<PaymentResult> response = new Response<>();
                response.setCode(StatusEnum.DATA_ERROR.code());
                response.setMsg(StatusEnum.DATA_ERROR.description());
                return response;
        }

    }

    private synchronized Response<PaymentResult> mdRecharge(PayOrderDV payOrderDV) {
        Response<PaymentResult> response = new Response<>();
        if(payOrderDV.getType() != PaymentTypeEnum.RECHARGE.type()){
            //美豆无法支付
            response.setCode(StatusEnum.DATA_ERROR.code());
            response.setMsg(StatusEnum.DATA_ERROR.description());
            return response;
        }

        String dealPwd = userService.getUserDealPwd(payOrderDV.getUserId());
        if(!dealPwd.equals(MyUtil.MD5encode(payOrderDV.getDealPwd()))){
            response.setCode(StatusEnum.VD_ERROR_DEAL_PWD.code());
            response.setMsg(StatusEnum.VD_ERROR_DEAL_PWD.description());
            return response;
        }

        if(!accountService.mdRecharge(payOrderDV.getUserId(),payOrderDV.getTotal())){
            //余额不足
            response.setCode(StatusEnum.ACCOUNT_NOT_ENOUGH.code());
            response.setMsg(StatusEnum.ACCOUNT_NOT_ENOUGH.description());
            return response;
        }

        PaymentResult paymentResult = new PaymentResult();
        paymentResult.setTrade_no(payOrderDV.getOrderNo());
        response.setData(paymentResult);
        response.setCode(StatusEnum.SUCCESS.code());
        response.setMsg(StatusEnum.SUCCESS.description());
        return response;
    }

    private Response<PaymentResult> zfbPay(PayOrderDV payOrderDV) {

        return ZFBPayUtil.createPreOrder(preZFBorderParam(payOrderDV));
    }

    private ZFBPayDV preZFBorderParam(PayOrderDV payOrderDV) {
        ZFBPayDV zfbPayDV = new ZFBPayDV();
        zfbPayDV.setSubject(payOrderDV.getTitle());
        zfbPayDV.setOut_trade_no(payOrderDV.getOrderNo());
        zfbPayDV.setTotal_amount(payOrderDV.getTotal());

        return zfbPayDV;
    }

    private Response<PaymentResult> wxPay(PayOrderDV payOrderDV) {

        return WXPayUtil.createPreOrder(preWXorderParam(payOrderDV));
    }

    private WXPayDV preWXorderParam(PayOrderDV payOrderDV) {
        WXPayDV wxPayDV = new WXPayDV();
        wxPayDV.setBody(payOrderDV.getTitle());
        wxPayDV.setSpbill_create_ip(payOrderDV.getIp());
        wxPayDV.setOut_trade_no(payOrderDV.getOrderNo());
        wxPayDV.setTotal_fee((int) (payOrderDV.getTotal()*100));
        return wxPayDV;
    }

    private synchronized Response<PaymentResult> gwjPay(PayOrderDV payOrderDV) {

        Response<PaymentResult> response = new Response<>();
        PaymentResult paymentResult = new PaymentResult();
        if(payOrderDV.getType() == PaymentTypeEnum.RECHARGE.type()){
            //购物金无法充值
            response.setCode(StatusEnum.DATA_ERROR.code());
            response.setMsg(StatusEnum.DATA_ERROR.description());
            return response;
        }

        String dealPwd = userService.getUserDealPwd(payOrderDV.getUserId());
        if(!dealPwd.equals(MyUtil.MD5encode(payOrderDV.getDealPwd()))){
            response.setCode(StatusEnum.VD_ERROR_DEAL_PWD.code());
            response.setMsg(StatusEnum.VD_ERROR_DEAL_PWD.description());
            return response;
        }

        if(!accountService.gwjPay(payOrderDV.getUserId(),payOrderDV.getTotal())){
            //余额不足
            response.setCode(StatusEnum.ACCOUNT_NOT_ENOUGH.code());
            response.setMsg(StatusEnum.ACCOUNT_NOT_ENOUGH.description());
            return response;
        }

        String tradeNo = getGwjNO();//生成购物金支付流水号
        Order order = orderService.findOrderByNo(payOrderDV.getOrderNo());
        orderService.updateStatus(payOrderDV.getUserId(),order.getId(),OrderStatusEnum.DELIVERY.type());
        //直推返利
        directIncomeHelper.incomeOrLvUp(payOrderDV.getOrderNo());
        paymentResult.setTrade_no(tradeNo);
        response.setData(paymentResult);
        response.setCode(StatusEnum.SUCCESS.code());
        response.setMsg(StatusEnum.SUCCESS.description());
        return response;
    }

    private String getGwjNO() {
        return "WGJ"+ UuidUtil.nowDateUuid();
    }

    @Transactional
    @Override
    public Response<Boolean> wxPayRT(WXPayRTDV wxPayRTDV) {
        log.info("*************微信app支付回调参数:{}",MyUtil.toJSON(wxPayRTDV));
        Response<Boolean> response = new Response<>();

        //查询订单


        OrderPayment orderPayment = orderPaymentMapper.findOrderPaymentByOrderNO(wxPayRTDV.getOut_trade_no());
        if(orderPayment != null){
            Date nowTime = new Date();
            orderPayment.setPayTime(nowTime);
            orderPayment.setCompleteTime(nowTime);
            orderPayment.setStatus(OrderPaymentStatusEnum.SUCCESS.type());
            orderPaymentMapper.updateByPrimaryKey(orderPayment);
            if(orderPayment.getType() == PaymentTypeEnum.RECHARGE.type()){
                //充值订单没有orderId
                accountService.wxzfgRecharge(orderPayment.getUserId(),orderPayment.getTotal(),ChangeTypeEnum.WX_RECHARGE.type());
                response.setCode(StatusEnum.SUCCESS.code());
                response.setMsg(StatusEnum.SUCCESS.description());
                response.setData(true);
                return response;
            }

            orderService.updateStatus(orderPayment.getUserId(),orderPayment.getOrderId(),OrderStatusEnum.DELIVERY.type());
            orderExpressService.updateExpressStatus(orderPayment.getOrderId(),OrderExpressStatusEnum.DELIVERY.type());
            //直推返利
            directIncomeHelper.incomeOrLvUp(wxPayRTDV.getOut_trade_no());
        }


        response.setCode(StatusEnum.SUCCESS.code());
        response.setMsg(StatusEnum.SUCCESS.description());
        response.setData(true);
        return response;
    }

    @Transactional
    @Override
    public Response<Boolean> zfbPayRT(ZFBPayRTDV zfbPayRTDV) {
        log.info(".............支付宝app支付回调参数:{}",MyUtil.toJSON(zfbPayRTDV));
        Response<Boolean> response = new Response<>();
        OrderPayment orderPayment = orderPaymentMapper.findOrderPaymentByOrderNO(zfbPayRTDV.getOut_trade_no());
        if(orderPayment != null){
            Date nowTime = new Date();
            orderPayment.setPayTime(nowTime);
            orderPayment.setCompleteTime(nowTime);
            orderPayment.setStatus(OrderPaymentStatusEnum.SUCCESS.type());
            orderPayment.setTradeNo(zfbPayRTDV.getTrade_no());
            orderPaymentMapper.updateByPrimaryKey(orderPayment);
            if(orderPayment.getType() == PaymentTypeEnum.RECHARGE.type()){
                accountService.wxzfgRecharge(orderPayment.getUserId(),orderPayment.getTotal(),ChangeTypeEnum.ZFB_RECHARGE.type());
                response.setCode(StatusEnum.SUCCESS.code());
                response.setMsg(StatusEnum.SUCCESS.description());
                response.setData(true);
                return response;
            }
            orderService.updateStatus(orderPayment.getUserId(),orderPayment.getOrderId(),OrderStatusEnum.DELIVERY.type());
            orderExpressService.updateExpressStatus(orderPayment.getOrderId(),OrderExpressStatusEnum.DELIVERY.type());

            //直推返利
            directIncomeHelper.incomeOrLvUp(zfbPayRTDV.getOut_trade_no());
        }


        response.setCode(StatusEnum.SUCCESS.code());
        response.setMsg(StatusEnum.SUCCESS.description());
        response.setData(true);
        return response;
    }

    @Override
    public Date getPayTime(int orderId) {
        return orderPaymentMapper.getPayTime(orderId);
    }


    private String getRechargeNO() {
        return "KVMRC"+UuidUtil.nowDateUuid();
    }

}
